home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume21 / coda / part02 < prev    next >
Encoding:
Internet Message Format  |  1990-04-08  |  47.6 KB

  1. Subject:  v21i085:  File distribution alternative to rdist, Part02/03
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 975c0789 2935d6ec 78d09f97 9606663f
  5.  
  6. Submitted-by: Rich Salz <rsalz@bbn.com>
  7. Posting-number: Volume 21, Issue 85
  8. Archive-name: coda/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 2 (of 3)."
  17. # Contents:  adt.c codaserver.8 file.c libvms.c server.c server.h
  18. # Wrapped by rsalz@litchi.bbn.com on Mon Apr  9 16:49:04 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'adt.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'adt.c'\"
  22. else
  23. echo shar: Extracting \"'adt.c'\" \(6748 characters\)
  24. sed "s/^X//" >'adt.c' <<'END_OF_FILE'
  25. X/*
  26. X**  Copyright 1989 BBN Systems and Technologies Corporation.
  27. X**  All Rights Reserved.
  28. X**  This is free software, and may be distributed under the terms of the
  29. X**  GNU Public License; see the file COPYING for more details.
  30. X**
  31. X**  Data abstractions for CODA server.
  32. X*/
  33. X#include "server.h"
  34. X#include <sys/stat.h>
  35. X#ifdef    RCSID
  36. Xstatic char RCS[] =
  37. X    "$Header: adt.c,v 2.0 90/03/23 14:40:58 rsalz Exp $";
  38. X#endif    /* RCSID */
  39. X
  40. X
  41. X/*
  42. X**  A class maps a name to a list of strings.  It's like a recursive
  43. X**  definition of a collection.  We keep a linked list of all our maps.
  44. X*/
  45. Xtypedef struct _CLASS {
  46. X    struct _CLASS    *Next;        /* Next one            */
  47. X    char        *Name;        /* The name            */
  48. X    int            NumHosts;    /* Number of hosts in the class    */
  49. X    int            MaxHosts;    /* Amount of space allocated    */
  50. X    char        **Hosts;    /* List of hosts        */
  51. X    int            NumClasses;    /* Number of classes        */
  52. X    int            MaxClasses;    /* Amount of space allocated    */
  53. X    char        **Classes;    /* List of classes in the class    */
  54. X} CLASS;
  55. X
  56. X
  57. XSTATIC CLASS    BaseClass;        /* Our linked list of classes    */
  58. XSTATIC STRLIST    BaseHost;        /* List of hosts in Codafile    */
  59. XSTATIC int    MaxItem;        /* Size of "Item" array        */
  60. X
  61. X
  62. X
  63. X/*
  64. X**  Remove all defined blocks, classes, and hosts.  This is not likely to
  65. X**  be called too often, so just flush memory -- the Add...() routines
  66. X**  share pointers so a free'ing would be a bit of work.  We use shared
  67. X**  pointers not to save space, but to make string compares fast.
  68. X*/
  69. Xvoid
  70. XResetStorage()
  71. X{
  72. X    BaseBlock.Next = NULL;
  73. X    BaseClass.Next = NULL;
  74. X    BaseHost.Next = NULL;
  75. X    ResetItem();
  76. X}
  77. X
  78. X
  79. Xvoid
  80. XResetItem()
  81. X{
  82. X    register ITEM    *I;
  83. X    register ITEM    *Iend;
  84. X
  85. X    NumItem = 0;
  86. X    if (BaseItem == NULL) {
  87. X    /* Since we can't trust realloc(NULL, ...) yet... */
  88. X    MaxItem = ITEM_DELTA;
  89. X    BaseItem = NEW(ITEM, MaxItem);
  90. X    }
  91. X    else
  92. X    /* Free old strings. */
  93. X    for (I = BaseItem, Iend = &BaseItem[NumItem]; I < Iend; I++)
  94. X        free(I->Name);
  95. X}
  96. X
  97. X
  98. X
  99. X/*
  100. X**  Guarantee an instantiation of a class.
  101. X*/
  102. XSTATIC CLASS *
  103. XFindOrCreateClass(Name)
  104. X    register char    *Name;
  105. X{
  106. X    register CLASS    *C;
  107. X
  108. X    /* Rummage through the list. */
  109. X    for (C = BaseClass.Next; C; C = C->Next)
  110. X    if (EQ(C->Name, Name))
  111. X        return C;
  112. X
  113. X    /* Create a new class, add it to the list. */
  114. X    C = NEW(CLASS, 1);
  115. X    C->Next = BaseClass.Next;
  116. X    C->Name = Name;
  117. X    C->NumHosts = 0;
  118. X    C->MaxHosts = HOST_DELTA;
  119. X    C->Hosts = NEW(char*, C->MaxHosts);
  120. X    C->NumClasses = 0;
  121. X    C->MaxClasses = CLASS_DELTA;
  122. X    C->Classes = NEW(char*, C->MaxClasses);
  123. X    BaseClass.Next = C;
  124. X    return C;
  125. X}
  126. X
  127. X
  128. X/*
  129. X**  Add a host to a class.
  130. X*/
  131. Xvoid
  132. XAddHostToClass(Name, Host)
  133. X    register char    *Name;
  134. X    register char    *Host;
  135. X{
  136. X    register char    **str;
  137. X    register CLASS    *C;
  138. X    register int    i;
  139. X
  140. X    C = FindOrCreateClass(Name);
  141. X
  142. X    /* Look through list of hosts, see if it's already there. */
  143. X    for (i = C->NumHosts, str = C->Hosts; --i >= 0; str++)
  144. X    if (EQ(Host, *str))
  145. X        return;
  146. X
  147. X    /* Have to add it; do we need more room? */
  148. X    if (C->NumHosts == C->MaxHosts - 1) {
  149. X    C->MaxHosts += HOST_DELTA;
  150. X    C->Hosts = GROW(C->Hosts, char*, C->MaxHosts);
  151. X    }
  152. X
  153. X    /* Add it. */
  154. X    C->Hosts[C->NumHosts++] = Host;
  155. X}
  156. X
  157. X
  158. X/*
  159. X**  Add a class to a class.
  160. X*/
  161. XSTATIC void
  162. XAddClassToClass(C, Name)
  163. X    register CLASS    *C;
  164. X    register char    *Name;
  165. X{
  166. X    register char    **str;
  167. X    register int    i;
  168. X
  169. X    /* Look through list of classes, see if it's already there. */
  170. X    for (i = C->NumClasses, str = C->Classes; --i >= 0; str++)
  171. X    if (EQ(Name, *str))
  172. X        return;
  173. X
  174. X    /* Have to add it; do we need more room? */
  175. X    if (C->NumClasses == C->MaxClasses - 1) {
  176. X    C->MaxClasses += CLASS_DELTA;
  177. X    C->Classes = GROW(C->Classes, char*, C->MaxClasses);
  178. X    }
  179. X
  180. X    /* Add it. */
  181. X    C->Classes[C->NumClasses++] = Name;
  182. X}
  183. X
  184. X
  185. X
  186. X/*
  187. X**  Add a list of classes to a class.
  188. X*/
  189. Xvoid
  190. XAddClassesToClass(Name, L)
  191. X    register char    *Name;
  192. X    register STRLIST    *L;
  193. X{
  194. X    register CLASS    *C;
  195. X
  196. X    for (C = FindOrCreateClass(Name); L; L = L->Next)
  197. X    AddClassToClass(C, L->Value);
  198. X}
  199. X
  200. X
  201. X
  202. X/*
  203. X**  Return TRUE if the host is a member of the specified class.
  204. X*/
  205. Xint
  206. XHostIsInClass(Host, Class)
  207. X    register char    *Host;
  208. X    register char    *Class;
  209. X{
  210. X    static char        Everyone[] = ALL;
  211. X    register char    **str;
  212. X    register CLASS    *C;
  213. X    register int    i;
  214. X
  215. X    /* Almost everyone is in the built-in class. */
  216. X    if (EQ(Class, Everyone))
  217. X    return !EQ(Host, UnknownHost) && HostWasDeclared(Host);
  218. X
  219. X    /* Nobody is in undefined classes. */
  220. X    for (C = BaseClass.Next; C; C = C->Next)
  221. X    if (EQ(C->Name, Class))
  222. X        break;
  223. X    if (C == NULL)
  224. X    return FALSE;
  225. X
  226. X    /* Look through list of hosts, see if it's already there. */
  227. X    for (i = C->NumHosts, str = C->Hosts; --i >= 0; str++)
  228. X    if (EQ(Host, *str))
  229. X        return TRUE;
  230. X
  231. X    /* Recursively look through list of classes. */
  232. X    for (i = C->NumClasses, str = C->Classes; --i >= 0; str++)
  233. X    if (HostIsInClass(Host, *str))
  234. X        return TRUE;
  235. X
  236. X    /* Not there. */
  237. X    return FALSE;
  238. X}
  239. X
  240. X
  241. X/*
  242. X**  Look through the list of hosts, see if we've got that one.
  243. X*/
  244. Xint
  245. XHostWasDeclared(Name)
  246. X    register char    *Name;
  247. X{
  248. X    register STRLIST    *S;
  249. X
  250. X    /* Rummage through the list. */
  251. X    for (S = BaseHost.Next; S; S = S->Next)
  252. X    if (EQ(S->Value, Name))
  253. X        return TRUE;
  254. X
  255. X    return FALSE;
  256. X}
  257. X
  258. X
  259. X/*
  260. X**  Add a host to our list of known hosts.
  261. X*/
  262. Xvoid
  263. XDefineHost(Host, Class)
  264. X    char    *Host;
  265. X    char    *Class;
  266. X{
  267. X    STRLIST    *S;
  268. X
  269. X    S = NEW(STRLIST, 1);
  270. X    S->Value = Host;
  271. X    S->Next = BaseHost.Next;
  272. X    BaseHost.Next = S;
  273. X    AddHostToClass(Class, Host);
  274. X}
  275. X
  276. X
  277. X
  278. X/*
  279. X**  Look through the list of blocks, see if we've got that one.
  280. X*/
  281. XBLOCK *
  282. XFindBlock(Name)
  283. X    register char    *Name;
  284. X{
  285. X    register BLOCK    *B;
  286. X
  287. X    /* Rummage through the list. */
  288. X    for (B = BaseBlock.Next; B; B = B->Next)
  289. X    if (EQ(B->Name, Name))
  290. X        return B;
  291. X    return NULL;
  292. X}
  293. X
  294. X
  295. X
  296. X/*
  297. X**  Add to the list of things sent.
  298. X*/
  299. Xvoid
  300. XAddItemToList(Name, Sb)
  301. X    char    *Name;
  302. X    struct stat    *Sb;
  303. X{
  304. X    ITEM    *I;
  305. X
  306. X    /* Need more room? */
  307. X    if (NumItem == MaxItem - 1) {
  308. X    MaxItem += ITEM_DELTA;
  309. X    BaseItem = GROW(BaseItem, ITEM, MaxItem);
  310. X    }
  311. X
  312. X    I = &BaseItem[NumItem++];
  313. X    I->Name    = COPY(Name);
  314. X    I->Uid    = Sb->st_uid;
  315. X    I->Gid    = Sb->st_gid;
  316. X    I->Directory= (Sb->st_mode & S_IFMT) == S_IFDIR;
  317. X    I->Size    = Sb->st_size;
  318. X    I->Time    = Sb->st_mtime;
  319. X    I->Mode    = Sb->st_mode & 0777;
  320. X}
  321. X
  322. X
  323. XSTATIC int
  324. XItemCompare(I1, I2)
  325. X    ITEM    *I1;
  326. X    ITEM    *I2;
  327. X{
  328. X    return strcmp(I1->Name, I2->Name);
  329. X}
  330. X
  331. X
  332. X/*
  333. X**  Sort our array.
  334. X*/
  335. Xvoid
  336. XSortItem()
  337. X{
  338. X    qsort((char *)BaseItem, NumItem, sizeof *BaseItem, ItemCompare);
  339. X}
  340. X
  341. X
  342. X/*
  343. X**  Use the bsearch() routine to find the item.
  344. X*/
  345. XITEM *
  346. XFindItem(Name)
  347. X    char    *Name;
  348. X{
  349. X    ITEM    *I;
  350. X    ITEM    Key;
  351. X
  352. X    Key.Name = Name;
  353. X    I = (ITEM *)bsearch((char *)&Key, (char *)BaseItem,
  354. X            (unsigned int)NumItem, sizeof *BaseItem, ItemCompare);
  355. X    return I;
  356. X}
  357. END_OF_FILE
  358. if test 6748 -ne `wc -c <'adt.c'`; then
  359.     echo shar: \"'adt.c'\" unpacked with wrong size!
  360. fi
  361. # end of 'adt.c'
  362. fi
  363. if test -f 'codaserver.8' -a "${1}" != "-c" ; then 
  364.   echo shar: Will not clobber existing file \"'codaserver.8'\"
  365. else
  366. echo shar: Extracting \"'codaserver.8'\" \(5278 characters\)
  367. sed "s/^X//" >'codaserver.8' <<'END_OF_FILE'
  368. X.TH CODASERVER 8 LOCAL
  369. X.SH NAME
  370. Xcodaserver \- Code distribution aid daemon
  371. X.SH SYNOPSIS
  372. X.B codaserver
  373. X[
  374. X.B \-c
  375. X] [
  376. X.BI \-l file
  377. X] [
  378. X.BI \-r file
  379. X] [
  380. X.B \-t
  381. X]
  382. X.SH DESCRIPTION
  383. X.I Codaserver
  384. Xis the server for the code distribution system.
  385. XIt should be installed on any system where you want clients to be able
  386. Xto pick up files.
  387. X.PP
  388. X.I Codaserver
  389. Xis normally started as necessary by the inet daemon.
  390. XTo run it in an interactive test mode, use the ``\-t'' flag; this will
  391. Xread commands from standard input and echo results to standard output.
  392. XTo test the syntax of a codafile, use the ``\-r'' flag; this will read
  393. Xand parse the file, and report any errors to standard output.
  394. X.PP
  395. X.I Codaserver
  396. Xreports all transactions to a log file, normally
  397. X.IR /usr/spool/log/codalog .
  398. XTo specify a different log file, use the ``\-l'' flag; the name ``\-'' is
  399. Xtaken to mean standard output.
  400. XFor each in decoding the logs, every message is stamped with the process-id
  401. Xand a sequence number.
  402. X.PP
  403. XSee the
  404. X.I coda
  405. Xmanual page for a description of the
  406. X.I Codafile
  407. Xlanguage.
  408. X.PP
  409. XThe ``\-c'' flag prints out copyright and version information.
  410. X.SH PROTOCOL
  411. XThe coda server uses a simple protocol running over a TCP stream.
  412. XCommands and their responses are exchanged in ASCII, and lines are
  413. Xterminated by a carriage-return/news line pair.
  414. XIt is easy to debug the system by connecting to the server with a
  415. X.IR telnet (1)
  416. Xto the right port.
  417. X.SS "Message Types"
  418. X.PP
  419. XUpon first connecting, the server will send an acknowledgement; after
  420. Xthis the server will only reply to messages sent from the client.
  421. XEvery non-blank line sent to the server will result in one or more
  422. Xlines of reply that ultimately end with an
  423. X.I ACK
  424. Xor
  425. X.I NAK
  426. Xmessage.
  427. X.PP
  428. XAll messages from the server are preceded by a three-character code.
  429. XIf the fourth character is a space, the server has more data to
  430. Xsend (as in the
  431. X.I help
  432. Xcommand); if the fourth character is a dash, this line has the
  433. Xserver's final reply to the client's request.
  434. XThe following message types are sent by the server:
  435. X.TP
  436. X.I ACK
  437. X.br
  438. XThe last command successfully completed;
  439. Xthe rest of the line may contain some information.
  440. X.TP
  441. X.I NAK
  442. X.br
  443. Xthe rest of the line should give an explanation for the failure.
  444. X.TP
  445. X.I INF
  446. X.br
  447. XInformation line intended for the user (e.g., help output).
  448. X.TP
  449. X.I DAT
  450. X.br
  451. XData lines intended for client programs (e.g., file lists).
  452. XThe rest of the line is interpreted by the client program.
  453. XThere is currently one type of data line, it describes a file or
  454. Xdirectory to be loaded by the client.
  455. XAfter the four-character identifier are the four letters
  456. X.I ITEM
  457. Xand a space.
  458. XThe remainder of the line is a set of space-separated key-value
  459. Xpairs, where the key is a single letter followed by an equal
  460. Xsign.
  461. XThe values are all interpreted in a Unix context; numbers are sent
  462. Xin decimal.
  463. XThe current keys are:
  464. X.RS
  465. X.nf
  466. X    W    Type; \fId\fP for directory, \fIf\fP for file
  467. X    N    Name of the file as text
  468. X    U    The numeric id of the item's owner
  469. X    G    The numeric id of the item's group
  470. X    M    The decimal value of the item's permission bits
  471. X    S    The size of the item in bytes
  472. X    T    The modification date of the file
  473. X.fi
  474. X.RE
  475. X.SS "Server Commands"
  476. X.PP
  477. XCommands consist of a word, possibly followed by an argument.
  478. XThe command word may be in either case.
  479. XThe coda server understands the following commands:
  480. X.TP
  481. X.I "GOTO dir"
  482. X.br
  483. XThe argument is a directory for the server to
  484. X.IR chdir (2)
  485. Xto.
  486. XThis command is not as useful as it used to be.
  487. X.TP
  488. X.I "HELP"
  489. X.br
  490. XDescribe the available commands.
  491. X.TP
  492. X.I "HOST name"
  493. X.br
  494. XSet the name of the apparent destination host.
  495. XThis command is only available in test mode.
  496. XThe host name is converted to uppercase.
  497. X.TP
  498. X.I "LIST [block]"
  499. X.br
  500. XAfter a
  501. X.I read
  502. Xcommand, this will list walk through the directories listed in the
  503. XCodafile and send a set of data line listing all the files and
  504. Xdirectories that are applicable for the client system.
  505. XIf no block name is given, all applicable blocks in the file are walked.
  506. X.TP
  507. X.I "MESG [text]"
  508. X.br
  509. XThe text is written to the server's log file.
  510. X.TP
  511. X.I "QUIT"
  512. X.br
  513. XThe server exits.
  514. X.TP
  515. X.I "READ [file]"
  516. X.br
  517. XRead the indicated Codafile; the default is
  518. X.IR Codafile .
  519. XThis resets any root value that might have been previously set,
  520. Xand clears the item list.
  521. X.TP
  522. X.I "ROOT [path]"
  523. X.br
  524. XSet the root directory for relative pathnames.
  525. XThis can be used to override the root after a
  526. X.I read
  527. Xcommand has been given.
  528. XThe default path is 
  529. X.IR / .
  530. X.TP
  531. X.I "SEND filename"
  532. X.br
  533. XAfter a
  534. X.I list
  535. Xcommand, this sends back an
  536. X.I ACK
  537. Xmessage, the uninterpreted bytes in the file, and a second
  538. X.I ACK
  539. Xmessage.
  540. XThe client must remember (from the
  541. X.I list
  542. Xcommand)
  543. Xhow big the file is so it knows how much data to expect.
  544. XOnly items mentioned in the most recent
  545. X.I list
  546. Xcommand can be sent.
  547. X.TP
  548. X.I "USER name pass"
  549. XLog in with the given name and password; only the
  550. X.I help
  551. Xand
  552. X.I mesg
  553. Xcommands can be used without logging in.
  554. X.SH AUTHOR
  555. XThis program was written by Rich $alz <rsalz@bbn.com>.
  556. XIt has the following copyright:
  557. X.RS
  558. X.nf
  559. XCopyright 1989 BBN Systems and Technologies Corporation.
  560. XAll Rights Reserved.
  561. XThis is free software, and may be distributed under the terms of the
  562. XGNU Public License; see the file COPYING for more details.
  563. X
  564. X$Header: codaserver.8,v 2.0 90/03/23 15:02:01 rsalz Exp $
  565. X.fi
  566. X.RE
  567. X.SH "SEE ALSO"
  568. Xcoda(1).
  569. END_OF_FILE
  570. if test 5278 -ne `wc -c <'codaserver.8'`; then
  571.     echo shar: \"'codaserver.8'\" unpacked with wrong size!
  572. fi
  573. # end of 'codaserver.8'
  574. fi
  575. if test -f 'file.c' -a "${1}" != "-c" ; then 
  576.   echo shar: Will not clobber existing file \"'file.c'\"
  577. else
  578. echo shar: Extracting \"'file.c'\" \(8889 characters\)
  579. sed "s/^X//" >'file.c' <<'END_OF_FILE'
  580. X/*
  581. X**  Copyright 1989 BBN Systems and Technologies Corporation.
  582. X**  All Rights Reserved.
  583. X**  This is free software, and may be distributed under the terms of the
  584. X**  GNU Public License; see the file COPYING for more details.
  585. X**
  586. X**  File routines for the CODA server.
  587. X*/
  588. X#include "server.h"
  589. X#include <sys/types.h>
  590. X#include <sys/stat.h>
  591. X#include <sys/dir.h>
  592. X#include <a.out.h>
  593. X#ifdef    RCSID
  594. Xstatic char RCS[] =
  595. X    "$Header: file.c,v 2.0 90/03/23 14:41:23 rsalz Exp $";
  596. X#endif    /* RCSID */
  597. X
  598. XSTATIC int    RootLen;        /* Length of the root string    */
  599. XSTATIC int    ScanCount;        /* How much have we looked at?    */
  600. X
  601. X/*
  602. X**  Yet another routine to walk through a directory tree.  It is similar
  603. X**  to ftw(3), but different.  It is not based on licensed code.
  604. X*/
  605. XSTATIC int
  606. XFileWalk(Path, Predicate, Depth, UserData)
  607. X    char        *Path;
  608. X    int            (*Predicate)();
  609. X    int            Depth;
  610. X    char        *UserData;
  611. X{
  612. X    register DIR    *Dp;
  613. X    register char    *p;
  614. X    register int    i;
  615. X    struct direct    *E;
  616. X    struct stat        Sb;
  617. X    long        cookie;
  618. X    char        fullpath[MAXPATH];
  619. X
  620. X    /* If we can't stat, pass it to the user but go no further. */
  621. X    if (stat(Path, &Sb) < 0) {
  622. X    (void)(*Predicate)(Path, (struct stat *)NULL, UserData);
  623. X    return FW_NOFURTHER;
  624. X    }
  625. X
  626. X    /* Call the user's function. */
  627. X    switch ((*Predicate)(Path, &Sb, UserData)) {
  628. X    default:
  629. X    case FW_NOFURTHER:
  630. X    return FW_NOFURTHER;
  631. X    case FW_EXIT:
  632. X    return FW_EXIT;
  633. X    case FW_PROCEED:
  634. X    if ((Sb.st_mode & S_IFMT) != S_IFDIR)
  635. X        return FW_PROCEED;
  636. X    break;
  637. X    }
  638. X
  639. X    /* Open directory; and if we can't tell the user so. */
  640. X    if ((Dp = opendir(Path)) == NULL)
  641. X    return FW_NOFURTHER;
  642. X
  643. X    /* For speed, remember where the last component starts. */
  644. X    i = strlen(Path);
  645. X    (void)strcpy(fullpath, Path);
  646. X    p = &fullpath[i];
  647. X    if (i && p[-1] != '/')
  648. X    *p++ = '/';
  649. X
  650. X    /* Read all entries in the directory. */
  651. X    while (E = readdir(Dp)) {
  652. X    if (EQ(E->d_name, ".") || EQ(E->d_name, ".."))
  653. X        continue;
  654. X
  655. X    /* If going too deep, remember our state and recycle. */
  656. X    if (Depth <= 1) {
  657. X        cookie = telldir(Dp);
  658. X        (void)closedir(Dp);
  659. X        Dp = NULL;
  660. X    }
  661. X
  662. X    /* Process the entry. */
  663. X    (void)strcpy(p, E->d_name);
  664. X    if (FileWalk(fullpath, Predicate, Depth - 1, UserData) == FW_EXIT) {
  665. X        /* User's finished; clean up. */
  666. X        if (Dp)
  667. X        (void)closedir(Dp);
  668. X        return FW_EXIT;
  669. X    }
  670. X
  671. X    /* Reopen the directory if necessary. */
  672. X    if (Dp == NULL) {
  673. X        if ((Dp = opendir(Path)) == NULL)
  674. X        /* WTF? */
  675. X        return FW_NOFURTHER;
  676. X        seekdir(Dp, cookie);
  677. X    }
  678. X    }
  679. X
  680. X    /* Clean up. */
  681. X    (void)closedir(Dp);
  682. X    return FW_PROCEED;
  683. X}
  684. X
  685. X
  686. X/*
  687. X**  Do shell-style pattern matching for ?, \, [], and * characters.
  688. X**  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  689. X**  could cause a segmentation violation.
  690. X**
  691. X**  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  692. X*/
  693. XSTATIC int
  694. XStar(s, p)
  695. X    register char    *s;
  696. X    register char    *p;
  697. X{
  698. X    STATIC int        Match();
  699. X
  700. X    while (Match(s, p) == FALSE)
  701. X    if (*++s == '\0')
  702. X        return FALSE;
  703. X    return TRUE;
  704. X}
  705. X
  706. XSTATIC int
  707. XMatch(s, p)
  708. X    register char    *s;
  709. X    register char    *p;
  710. X{
  711. X    register int    last;
  712. X    register int    matched;
  713. X    register int    reverse;
  714. X
  715. X    for ( ; *p; s++, p++)
  716. X    switch (*p) {
  717. X    case '\\':
  718. X        /* Literal match with following character. */
  719. X        p++;
  720. X        /* FALLTHROUGH */
  721. X    default:
  722. X        if (*s != *p)
  723. X        return FALSE;
  724. X        continue;
  725. X    case '?':
  726. X        /* Match anything. */
  727. X        if (*s == '\0')
  728. X        return FALSE;
  729. X        continue;
  730. X    case '*':
  731. X        /* Trailing star matches everything. */
  732. X        return *++p ? Star(s, p) : TRUE;
  733. X    case '[':
  734. X        /* [^....] means inverse character class. */
  735. X        if (reverse = p[1] == '^')
  736. X        p++;
  737. X        for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
  738. X        /* This next line requires a good C compiler. */
  739. X        if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
  740. X            matched = TRUE;
  741. X        if (matched == reverse)
  742. X        return FALSE;
  743. X        continue;
  744. X    }
  745. X
  746. X    return *s == '\0';
  747. X}
  748. X
  749. X
  750. X/*
  751. X**  Return TRUE if a file is an "a.out" file.
  752. X*/
  753. XSTATIC int
  754. XIsBinaryFile(Path)
  755. X    char    *Path;
  756. X{
  757. X    FILE    *F;
  758. X    struct exec    Head;
  759. X
  760. X    if ((F = fopen(Path, "r")) == NULL
  761. X     || fread((char *)&Head, sizeof Head, 1, F) != 1)
  762. X    return FALSE;
  763. X    (void)fclose(F);
  764. X    switch (Head.a_magic) {
  765. X    default:
  766. X    return FALSE;
  767. X#ifdef    OMAGIC
  768. X    case OMAGIC:
  769. X    return TRUE;
  770. X#endif    /* OMAGIC */
  771. X#ifdef    NMAGIC
  772. X    case NMAGIC:
  773. X    return TRUE;
  774. X#endif    /* NMAGIC */
  775. X#ifdef    ZMAGIC
  776. X    case ZMAGIC:
  777. X    return TRUE;
  778. X#endif    /* ZMAGIC */
  779. X    }
  780. X}
  781. X
  782. X
  783. X/*
  784. X**  This is the predicate for the file walker.  It gets passed the
  785. X**  current EXCEPTION block, to see if the Path is something we want
  786. X**  to add to our list or not.
  787. X*/
  788. XSTATIC int
  789. XAdder(Path, Sb, UserData)
  790. X    char        *Path;
  791. X    struct stat        *Sb;
  792. X    char        *UserData;
  793. X{
  794. X    register EXCEPTION    *E;
  795. X    register STRLIST    *S;
  796. X    register char    *tail;
  797. X
  798. X    /* Silently skip bogus entries. */
  799. X    if (Sb == NULL)
  800. X    return FW_NOFURTHER;
  801. X
  802. X    if (++ScanCount == SCAN_PING) {
  803. X    Message("Still scanning...");
  804. X    ScanCount = 0;
  805. X    }
  806. X
  807. X    /* Get last component. */
  808. X    if (tail = strrchr(Path, '/'))
  809. X    tail++;
  810. X    else
  811. X    tail = Path;
  812. X
  813. X    switch (Sb->st_mode & S_IFMT) {
  814. X    default:
  815. X    /* Something we don't handle. */
  816. X    return FW_PROCEED;
  817. X    case S_IFDIR:
  818. X    /* Look through all "directory" exceptions; if we find one for
  819. X     * the client's host, go no further. */
  820. X    for (E = (EXCEPTION *)UserData; E; E = E->Next)
  821. X        if (E->Directory && HostIsInClass(TheHost, E->Class))
  822. X        for (S = E->Value; S; S = S->Next) {
  823. X            if (*S->Value == '^' && Match(Path, &S->Value[1]))
  824. X            return FW_NOFURTHER;
  825. X            if (*S->Value != '^' && Match(tail, S->Value))
  826. X            return FW_NOFURTHER;
  827. X        }
  828. X    /* Make sure the user can hack on it. */
  829. X    Sb->st_mode |= S_IREAD | S_IWRITE | S_IEXEC;
  830. X        break;
  831. X    case S_IFREG:
  832. X    /* Normal file; if we don't want it, we still keep going. */
  833. X    for (E = (EXCEPTION *)UserData; E; E = E->Next)
  834. X        if (!E->Directory && HostIsInClass(TheHost, E->Class))
  835. X        for (S = E->Value; S; S = S->Next) {
  836. X            if (*S->Value == '^' && Match(Path, &S->Value[1]))
  837. X            return FW_PROCEED;
  838. X            if (*S->Value != '^' && Match(tail, S->Value))
  839. X            return FW_PROCEED;
  840. X        }
  841. X    if (!AllowBinaries && IsBinaryFile(Path))
  842. X        return FW_PROCEED;
  843. X    break;
  844. X    }
  845. X
  846. X    /* Add the item, tell the Walker to keep going. */
  847. X    if (strlen(Path) > RootLen
  848. X     && Path[RootLen] == '/'
  849. X     && strncmp(Path, TheRoot, RootLen) == 0)
  850. X    Path += RootLen + 1;
  851. X    AddItemToList(Path, Sb);
  852. X    return FW_PROCEED;
  853. X}
  854. X
  855. X
  856. X/*
  857. X**  Give status information on all the files in a block.
  858. X*/
  859. XSTATIC int
  860. XListFilesInBlock(B)
  861. X    BLOCK        *B;
  862. X{
  863. X    register DIRLIST    *D;
  864. X    register char    *p;
  865. X    struct stat        Sb;
  866. X    char        fullpath[MAXPATH];
  867. X
  868. X    /* Does the host get this block? */
  869. X    if (!HostIsInClass(TheHost, B->Class))
  870. X    return FALSE;
  871. X
  872. X    /* Loop over all directories in this block. */
  873. X    for (ScanCount = 0, D = B->Directories; D; D = D->Next) {
  874. X    /* Build the pathname. */
  875. X    if (*D->Value == '/')
  876. X        p = D->Value;
  877. X    else {
  878. X        (void)sprintf(fullpath, "%s/%s", TheRoot, D->Value);
  879. X        p = fullpath;
  880. X    }
  881. X    if (!D->Directory)
  882. X        (void)FileWalk(p, Adder, FASTDEPTH, (char *)D->Exceptions);
  883. X    else if (stat(p, &Sb) >= 0)
  884. X        /* Ignore exceptions? */
  885. X        AddItemToList(D->Value, &Sb);
  886. X    else
  887. X        /* Silently skip bogus files. */
  888. X        ;
  889. X    }
  890. X
  891. X    /* Done. */
  892. X    return TRUE;
  893. X}
  894. X
  895. X
  896. X/*
  897. X**  List all the files in the block.
  898. X*/
  899. Xvoid
  900. XListFiles(p)
  901. X    char        *p;
  902. X{
  903. X    register BLOCK    *B;
  904. X    register ITEM    *I;
  905. X    register ITEM    *Iend;
  906. X    char        buff[SIZE];
  907. X
  908. X    ResetItem();
  909. X    RootLen = strlen(TheRoot);
  910. X
  911. X    if (*p) {
  912. X    if ((B = FindBlock(p)) == NULL) {
  913. X        Nack("No such block");
  914. X        return;
  915. X    }
  916. X    if (!ListFilesInBlock(B)) {
  917. X        Nack("Host doesn't get that block");
  918. X        return;
  919. X    }
  920. X    }
  921. X    else
  922. X    /* List all blocks. */
  923. X    for (B = BaseBlock.Next; B; B = B->Next)
  924. X        if (!B->Excluded)
  925. X        (void)ListFilesInBlock(B);
  926. X
  927. X    SortItem();
  928. X    for (I = BaseItem, Iend = &BaseItem[NumItem]; I < Iend; I++) {
  929. X    (void)sprintf(buff, "ITEM W=%c N=%s U=%d G=%d M=%d S=%ld T=%ld",
  930. X            I->Directory ? 'd' : 'f', I->Name, I->Uid,
  931. X            I->Gid, I->Mode, (long)I->Size, (long)I->Time);
  932. X    Data(buff);
  933. X    }
  934. X
  935. X    (void)sprintf(buff, "Found %d files", NumItem);
  936. X    Ack(buff);
  937. X}
  938. X
  939. X
  940. X/*
  941. X**  Send one file down the pipe.
  942. X*/
  943. Xvoid
  944. XSendFile(Name)
  945. X    char        *Name;
  946. X{
  947. X    register FILE    *F;
  948. X    register int    C;
  949. X    ITEM        *I;
  950. X    char        fullpath[MAXPATH];
  951. X
  952. X    /* Can client get it? */
  953. X    if ((I = FindItem(Name)) == NULL) {
  954. X    Nack("File not found");
  955. X    return;
  956. X    }
  957. X
  958. X    /* Open it, dealing with relative pathnames. */
  959. X    if (Name[0] == '/')
  960. X    F = fopen(Name, "r");
  961. X    else {
  962. X    (void)sprintf(fullpath, "%s/%s", TheRoot, Name);
  963. X    F = fopen(fullpath, "r");
  964. X    }
  965. X    if (F == NULL) {
  966. X    Nack((char *)NULL);
  967. X    return;
  968. X    }
  969. X
  970. X    /* Send it. */
  971. X    Ack(Name);
  972. X    while ((C = getc(F)) != EOF)
  973. X    (void)putchar(C);
  974. X    (void)fclose(F);
  975. X#ifdef    VERBOSE_LOG
  976. X    LogSentItem(I);
  977. X#else
  978. X# ifdef    lint
  979. X    I = I;
  980. X# endif    /* lint */
  981. X#endif    /* VERBOSE_LOG */
  982. X    Ack((char *)NULL);
  983. X}
  984. END_OF_FILE
  985. if test 8889 -ne `wc -c <'file.c'`; then
  986.     echo shar: \"'file.c'\" unpacked with wrong size!
  987. fi
  988. # end of 'file.c'
  989. fi
  990. if test -f 'libvms.c' -a "${1}" != "-c" ; then 
  991.   echo shar: Will not clobber existing file \"'libvms.c'\"
  992. else
  993. echo shar: Extracting \"'libvms.c'\" \(7419 characters\)
  994. sed "s/^X//" >'libvms.c' <<'END_OF_FILE'
  995. X/*
  996. X**  Copyright 1989 BBN Systems and Technologies Corporation.
  997. X**  All Rights Reserved.
  998. X**  This is free software, and may be distributed under the terms of the
  999. X**  GNU Public License; see the file COPYING for more details.
  1000. X**
  1001. X**  Client library routines for VMS with Wollongong 3.0 TCP.
  1002. X**  Check the "/INCLUDE" qualifier in descrip.mms.
  1003. X**
  1004. X**  Our VMS documentation claims some functions exist that really don't,
  1005. X**  so we've had to implement them on our own.
  1006. X**
  1007. X**  Also, Wollongong's header files try to re-specify some of the same
  1008. X**  same typedef's that the VMS C RTL specifies.  Sigh.
  1009. X*/
  1010. X#include "client.h"
  1011. X#include <types.h>
  1012. X#include <string.h>
  1013. X#include <ssdef.h>
  1014. X#include <iodef.h>
  1015. X#include <descrip.h>
  1016. X#define time_t    TWG_time_t
  1017. X#define size_t    TWG_size_t
  1018. X#include "[sys]types2.h"
  1019. X#include "[sys]socket.h"
  1020. X#include "[netinet]in.h"
  1021. X#undef time_t
  1022. X#undef size_t
  1023. X#ifdef    RCSID
  1024. Xstatic char     RCS[] =
  1025. X    "$Header: libvms.c,v 2.0 90/04/09 16:29:34 rsalz Exp $";
  1026. X#endif    /* RCSID */
  1027. X
  1028. X
  1029. X/*
  1030. X**  Depending on what version of the C RTL you have, you will need to
  1031. X**  edit these.
  1032. X*/
  1033. X#define NEED_UTIME
  1034. X#undef NEED_RENAME
  1035. X#undef NEED_MEMSET
  1036. X
  1037. XSTATIC int     Channel;        /* Something to talk with    */
  1038. X
  1039. X
  1040. X#ifdef    NEED_UTIME
  1041. X#include "vmsutime.inc"
  1042. X#endif    /* NEED_UTIME */
  1043. X
  1044. X
  1045. X/*
  1046. X**  This comes from the AT&T public domain getopt handed out at 1985
  1047. X**  UNIFORUM and subsequently posted to Usenet.
  1048. X*/
  1049. Xint        opterr = 1;
  1050. Xint        optind = 1;
  1051. Xint        optopt;
  1052. Xchar        *optarg;
  1053. Xextern char    *strchr();
  1054. X
  1055. Xint
  1056. Xgetopt(ac, av, options)
  1057. X    int            ac;
  1058. X    char        **av;
  1059. X    char        *options;
  1060. X{
  1061. X    static int        sp = 1;
  1062. X    REGISTER char    *p;
  1063. X
  1064. X    if (sp == 1) {
  1065. X    if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0')
  1066. X        return EOF;
  1067. X    if (strcmp(av[optind], "--") == 0) {
  1068. X        optind++;
  1069. X        return EOF;
  1070. X    }
  1071. X    }
  1072. X
  1073. X    optopt = av[optind][sp];
  1074. X
  1075. X    /* Bogus flag? */
  1076. X    if (optopt == ':' || (p = strchr(options, optopt)) == NULL) {
  1077. X    if (opterr)
  1078. X        (void)fprintf(stderr, "%s: illegal option -- %c\n", av[0], optopt);
  1079. X    if (av[optind][++sp] == '\0') {
  1080. X        optind++;
  1081. X        sp = 1;
  1082. X    }
  1083. X    return '?';
  1084. X    }
  1085. X
  1086. X    /* Flag needs an option? */
  1087. X    if (*++p == ':') {
  1088. X    if (av[optind][sp + 1])
  1089. X        optarg = &av[optind++][sp + 1];
  1090. X    else if (++optind < ac)
  1091. X        optarg = av[optind++];
  1092. X    else {
  1093. X        if (opterr)
  1094. X        (void)fprintf(stderr,
  1095. X            "%s: option requires an argument -- %c\n",
  1096. X            av[0], optopt);
  1097. X        sp = 1;
  1098. X        return '?';
  1099. X    }
  1100. X    sp = 1;
  1101. X    }
  1102. X    else {
  1103. X    if (av[optind][++sp] == '\0') {
  1104. X        sp = 1;
  1105. X        optind++;
  1106. X    }
  1107. X    optarg = NULL;
  1108. X    }
  1109. X    return optopt;
  1110. X}
  1111. X
  1112. X
  1113. X#ifdef    NEED_MEMSET
  1114. X/*
  1115. X**  Set memory to a value.
  1116. X*/
  1117. Xvoid *
  1118. Xmemset(save, c, count)
  1119. X    void        *save;
  1120. X    int            c;
  1121. X    unsigned int    count;
  1122. X{
  1123. X    char        *p;
  1124. X    register int     i;
  1125. X
  1126. X    if ((i = count) != 0)
  1127. X    for (p = save; --i >= 0; )
  1128. X        *p++ = c;
  1129. X
  1130. X    return save;
  1131. X}
  1132. X#endif    /* NEED_MEMSET */
  1133. X
  1134. X
  1135. X#ifdef    NEED_RENAME
  1136. X/*
  1137. X**  Turn a nice pretty /unix/path/name into an ugly [.vms.path]name
  1138. X*/
  1139. XSTATIC void
  1140. XVMSname(path, buffer)
  1141. X    char        *path;
  1142. X    char        *buffer;
  1143. X{
  1144. X    REGISTER char    *p;
  1145. X    REGISTER char    *tail;
  1146. X    char        temp[SIZE];
  1147. X
  1148. X    /* Simple case "foo" ==> "foo" */
  1149. X    (void)strcpy(temp, path);
  1150. X    if ((tail = strrchr(temp, '/')) == NULL) {
  1151. X    strcpy(buffer, path);
  1152. X    return;
  1153. X    }
  1154. X
  1155. X    /* Split off the last component. */
  1156. X    *tail++ = '\0';
  1157. X
  1158. X    /* Turn all slashes into periods. */
  1159. X    for (p = temp; p = strchr(p, '/'); )
  1160. X    *p++ = '.';
  1161. X    if (temp[0] == '.')
  1162. X    (void)sprintf(buffer, "[%s]%s", &temp[1], tail);
  1163. X    else
  1164. X    (void)sprintf(buffer, "[.%s]%s", temp, tail);
  1165. X}
  1166. X
  1167. X
  1168. X/*
  1169. X**  Rename a file.
  1170. X*/
  1171. Xint
  1172. Xrename(from, to)
  1173. X    char            *from;
  1174. X    char            *to;
  1175. X{
  1176. X    struct dsc$descriptor_s    Fdesc;
  1177. X    struct dsc$descriptor_s    Tdesc;
  1178. X    char            Fname[SIZE];
  1179. X    char            Tname[SIZE];
  1180. X
  1181. X    VMSname(from, Fname);
  1182. X    Fdesc.dsc$a_pointer = Fname;
  1183. X    Fdesc.dsc$w_length  = strlen(Fname);
  1184. X    Fdesc.dsc$b_dtype   = DSC$K_DTYPE_T;
  1185. X    Fdesc.dsc$b_class   = DSC$K_CLASS_S;
  1186. X
  1187. X    VMSname(to, Tname);
  1188. X    Tdesc.dsc$a_pointer = Tname;
  1189. X    Tdesc.dsc$w_length  = strlen(Tname);
  1190. X    Tdesc.dsc$b_dtype   = DSC$K_DTYPE_T;
  1191. X    Tdesc.dsc$b_class   = DSC$K_CLASS_S;
  1192. X
  1193. X    return lib$rename_file(&Fdesc, &Tdesc) == SS$_NORMAL ? 0 : -1;
  1194. X}
  1195. X#endif    /* NEED_RENAME */
  1196. X
  1197. X
  1198. X/*
  1199. X**  Remove a file.
  1200. X*/
  1201. Xint
  1202. Xunlink(Name)
  1203. X    char    *Name;
  1204. X{
  1205. X    return delete(Name);
  1206. X
  1207. X}
  1208. X
  1209. X
  1210. X/*
  1211. X**  Do the grundge work of getting us a socket.
  1212. X*/
  1213. XSTATIC int
  1214. XGetSocket(machine, port)
  1215. X    char        *machine;
  1216. X    int            port;
  1217. X{
  1218. X    unsigned long    rhost();
  1219. X    REGISTER int    s;
  1220. X    char        *p;
  1221. X    struct sockaddr_in    sin;
  1222. X
  1223. X    /* Set up the socket. */
  1224. X    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  1225. X    perror("Socket creation failed");
  1226. X    return -1;
  1227. X    }
  1228. X
  1229. X    /* Set up the socket address. */
  1230. X    (void)memset((void *)&sin, '\0', sizeof sin);
  1231. X    p = machine;
  1232. X    if ((sin.sin_addr.s_addr = rhost(&p)) == -1) {
  1233. X    perror("No such machine");
  1234. X    return -1;
  1235. X    }
  1236. X    sin.sin_family = AF_INET;
  1237. X    sin.sin_port = htons(port);
  1238. X
  1239. X    /* Connect to the server. */
  1240. X    if (connect(s, &sin, sizeof sin) < 0) {
  1241. X    perror("Connect failed");
  1242. X    netclose(s);
  1243. X    return -1;
  1244. X    }
  1245. X
  1246. X    return s;
  1247. X}
  1248. X
  1249. X
  1250. X/*
  1251. X**  Open connection to server, return FALSE on error.
  1252. X*/
  1253. Xint
  1254. XSRVopen(machine, port)
  1255. X    char    *machine;
  1256. X    int        port;
  1257. X{
  1258. X    return (Channel = GetSocket(machine, port)) >= 0;
  1259. X}
  1260. X
  1261. X
  1262. X/*
  1263. X**  Send a QUIT and shut down.
  1264. X*/
  1265. Xvoid
  1266. XSRVclose()
  1267. X{
  1268. X    SRVput("QUIT");
  1269. X    (void)netclose(Channel);
  1270. X}
  1271. X
  1272. X
  1273. X/*
  1274. X**  Send a line to the server.
  1275. X*/
  1276. Xvoid
  1277. XSRVput(p)
  1278. X    char    *p;
  1279. X{
  1280. X    if (SRVtrace)
  1281. X    (void)printf(">>>%s\n", p);
  1282. X    netwrite(Channel, p, strlen(p));
  1283. X    netwrite(Channel, "\r\n", 2);
  1284. X}
  1285. X
  1286. X
  1287. X/*
  1288. X**  Get a line of text from the server.  Strip end-of-line characters.
  1289. X*/
  1290. Xint
  1291. XSRVget(buff, size)
  1292. X    char        *buff;
  1293. X    int            size;
  1294. X{
  1295. X    REGISTER char    *p;
  1296. X    REGISTER char    *bend;
  1297. X    REGISTER int    c;
  1298. X
  1299. X    for (bend = &buff[size - 1]; ; ) {
  1300. X    for (p = buff; ((c = SRVcget()) != '\n'); ) {
  1301. X        if (c == EOF)
  1302. X        return FALSE;
  1303. X        if (c != '\r' && p < bend)
  1304. X        *p++ = c;
  1305. X    }
  1306. X    *p = '\0';
  1307. X    if (SRVtrace)
  1308. X        (void)printf("<<<%s\n", buff);
  1309. X    if (strncmp(buff, "INF ", 4))
  1310. X        return TRUE;
  1311. X    (void)printf("Server message:\n\t%s\n", &buff[4]);
  1312. X    (void)fflush(stdout);
  1313. X    }
  1314. X}
  1315. X
  1316. X
  1317. X/*
  1318. X**  Get a character from the server.
  1319. X*/
  1320. Xint
  1321. XSRVcget()
  1322. X{
  1323. X    static char    buff[1024];
  1324. X    static int    count;
  1325. X    static int    max;
  1326. X
  1327. X    if (count == max) {
  1328. X    while ((max = netread(Channel, buff, sizeof buff)) == 0)
  1329. X        ;
  1330. X    if (max < 0)
  1331. X        return EOF;
  1332. X    if (max > sizeof buff)
  1333. X        (void)abort();
  1334. X    count = 0;
  1335. X    }
  1336. X    return buff[count++];
  1337. X}
  1338. X
  1339. X
  1340. X/*
  1341. X**  Get a password without echoing.
  1342. X*/
  1343. Xvoid
  1344. XGetPassword(buff, size)
  1345. X     char            *buff;
  1346. X     int            size;
  1347. X{
  1348. X    struct dsc$descriptor_s    Desc;
  1349. X    int                i;
  1350. X    int                kb;
  1351. X    int                mask;
  1352. X    int                timeout;
  1353. X    int                length;
  1354. X
  1355. X    /* Create a keyboard to read from. */
  1356. X    if (smg$create_virtual_keyboard(&kb) != SS$_NORMAL) {
  1357. X    perror("Error creating virtual_keyboard");
  1358. X    exit(i);
  1359. X    }
  1360. X
  1361. X    /* Set up the parameters. */
  1362. X    Desc.dsc$w_length = size;
  1363. X    Desc.dsc$b_dtype = DSC$K_DTYPE_T;
  1364. X    Desc.dsc$b_class = DSC$K_CLASS_S;
  1365. X    Desc.dsc$a_pointer = buff;
  1366. X    mask = IO$M_NOECHO;
  1367. X    timeout = 60;
  1368. X    length = 0;
  1369. X
  1370. X    /* Read it. */
  1371. X    i = smg$read_string(&kb, &Desc, 0, &size, &mask, &timeout, 0, &length);
  1372. X    if (i != SS$_NORMAL) {
  1373. X    perror("Error reading password");
  1374. X    exit(i);
  1375. X    }
  1376. X
  1377. X    /* Delete the keyboard. */
  1378. X    if (smg$delete_virtual_keyboard(&kb) != SS$_NORMAL) {
  1379. X    perror("Error deleting virtual keyboard");
  1380. X    exit(i);
  1381. X    }
  1382. X
  1383. X    /* Clean up and return. */
  1384. X    (void)printf("\n");
  1385. X    buff[length] = '\0';
  1386. X}
  1387. END_OF_FILE
  1388. if test 7419 -ne `wc -c <'libvms.c'`; then
  1389.     echo shar: \"'libvms.c'\" unpacked with wrong size!
  1390. fi
  1391. # end of 'libvms.c'
  1392. fi
  1393. if test -f 'server.c' -a "${1}" != "-c" ; then 
  1394.   echo shar: Will not clobber existing file \"'server.c'\"
  1395. else
  1396. echo shar: Extracting \"'server.c'\" \(9605 characters\)
  1397. sed "s/^X//" >'server.c' <<'END_OF_FILE'
  1398. X/*
  1399. X**  Copyright 1989 BBN Systems and Technologies Corporation.
  1400. X**  All Rights Reserved.
  1401. X**  This is free software, and may be distributed under the terms of the
  1402. X**  GNU Public License; see the file COPYING for more details.
  1403. X**
  1404. X**  Main driver for CODA server.
  1405. X*/
  1406. X#define MAINLINE
  1407. X#include "server.h"
  1408. X#include <pwd.h>
  1409. X#include <signal.h>
  1410. X#include <setjmp.h>
  1411. X#include <sys/stat.h>
  1412. X#include <sys/socket.h>
  1413. X#include <netinet/in.h>
  1414. X#include <netdb.h>
  1415. X#ifdef    RCSID
  1416. Xstatic char RCS[] =
  1417. X    "$Header: server.c,v 2.0 90/03/23 14:41:55 rsalz Exp $";
  1418. X#endif    /* RCSID */
  1419. X
  1420. X
  1421. X/*
  1422. X**  A command has a text name, an internal value, and a help message.
  1423. X*/
  1424. Xtypedef struct _TABLE {
  1425. X    char    *Name;
  1426. X    COMMAND    Value;
  1427. X    char    *Help;
  1428. X} TABLE;
  1429. X
  1430. Xchar        *LogFile = LOGFILE;    /* Name of the log file        */
  1431. Xchar        UnknownHost[] = GUESTHOST; /* For unknown hosts        */
  1432. X
  1433. XSTATIC jmp_buf    Context;        /* When the bell rings        */
  1434. XSTATIC BOOL    LoggedIn;        /* Did we get a USER command?    */
  1435. XSTATIC BOOL    Testing;        /* Are we in test mode?        */
  1436. X
  1437. XSTATIC TABLE    Commands[] = {        /* List of commands        */
  1438. X    {    "GOTO",        CMDgoto,    "Change to specified directory" },
  1439. X    {    "EXIT",        CMDquit,    "Shut down server" },
  1440. X    {    "HELP",        CMDhelp,    "Print this status report" },
  1441. X    {    "HOST",        CMDhost,    "Specify name of destination host" },
  1442. X    {    "MESG",        CMDmesg,    "Send message to log file" },
  1443. X    {    "LIST",        CMDlist,    "List status of files [in block]" },
  1444. X    {    "QUIT",        CMDquit,    "Shut down server" },
  1445. X    {    "READ",        CMDread,    "Read control file, name optional" },
  1446. X    {    "ROOT",        CMDroot,    "Set root for relative pathnames" },
  1447. X    {    "SEND",        CMDsend,    "Start file-sending protocol" },
  1448. X    {    "USER",        CMDuser,    "Log in a specified user" },
  1449. X    {    "",        CMD_time,    NULL },
  1450. X    { NULL }
  1451. X};
  1452. X
  1453. X
  1454. X
  1455. X/*
  1456. X**  Return a perror-style string.
  1457. X*/
  1458. Xchar *
  1459. Xstrerror(e)
  1460. X    int        e;
  1461. X{
  1462. X    extern int    sys_nerr;
  1463. X    extern char    *sys_errlist[];
  1464. X    char    buff[20];
  1465. X
  1466. X    if (e < 0 || e > sys_nerr) {
  1467. X    (void)sprintf(buff, "Error code %d\n", e);
  1468. X    return buff;
  1469. X    }
  1470. X    return sys_errlist[e];
  1471. X}
  1472. X
  1473. X
  1474. X
  1475. X/*
  1476. X**  Send a message saying a command was successful.
  1477. X*/
  1478. Xvoid
  1479. XAck(p)
  1480. X    char    *p;
  1481. X{
  1482. X    (void)printf("ACK-%s\r\n", p ? p : "Done");
  1483. X    (void)fflush(stdout);
  1484. X}
  1485. X
  1486. X
  1487. X/*
  1488. X**  Send a message saying that a command failed.
  1489. X*/
  1490. Xvoid
  1491. XNack(p)
  1492. X    char    *p;
  1493. X{
  1494. X    (void)printf("NAK-%s\r\n", p ? p : strerror(errno));
  1495. X    (void)fflush(stdout);
  1496. X}
  1497. X
  1498. X
  1499. X/*
  1500. X**  Send an information message.  The client shoujld pass these on to
  1501. X**  the user.
  1502. X*/
  1503. Xvoid
  1504. XMessage(p)
  1505. X    char    *p;
  1506. X{
  1507. X    (void)printf("INF %s\r\n", p ? p : "Never mind");
  1508. X}
  1509. X
  1510. X
  1511. X/*
  1512. X**  Send a data message.  This is for the client program.
  1513. X*/
  1514. Xvoid
  1515. XData(p)
  1516. X    char    *p;
  1517. X{
  1518. X    if (p)
  1519. X    (void)printf("DAT %s\r\n", p);
  1520. X}
  1521. X
  1522. X
  1523. X
  1524. X/*
  1525. X**  When that bell rings, get out of here!
  1526. X*/
  1527. XSTATIC CATCHER
  1528. XAlarmCatch()
  1529. X{
  1530. X    longjmp(Context, 1);
  1531. X    /* NOTREACHED */
  1532. X}
  1533. X
  1534. X
  1535. X/*
  1536. X**  Read a line from the client.  Quit if it times out.  Otherwise
  1537. X**  parse the first word as a command, stuff the rest of the line as
  1538. X**  a possible argument to the command, and return the command's value.
  1539. X*/
  1540. XSTATIC COMMAND
  1541. XReadLine(arg, size)
  1542. X    char        *arg;
  1543. X    int            size;
  1544. X{
  1545. X    register char    *p;
  1546. X    register char    *q;
  1547. X    register TABLE    *T;
  1548. X    char        buff[SIZE];
  1549. X
  1550. X    if (setjmp(Context) == 1)
  1551. X    return CMD_time;
  1552. X
  1553. X    for ( ; ; ) {
  1554. X    /* Timed-out read. */
  1555. X    (void)alarm(TIMEOUT);
  1556. X    p = fgets(buff, sizeof buff, stdin);
  1557. X    (void)alarm(0);
  1558. X    if (p == NULL)
  1559. X        return CMDquit;
  1560. X
  1561. X    /* Kill the terminator. */
  1562. X    if ((p = strchr(buff, '\r')) || (p = strchr(buff, '\n')))
  1563. X        *p = '\0';
  1564. X
  1565. X    /* Skip whitespace, ignore totally blank lines. */
  1566. X    for (p = buff; *p && WHITE(*p); p++)
  1567. X        ;
  1568. X    if (*p == '\0')
  1569. X        continue;
  1570. X
  1571. X    /* Find first word. */
  1572. X    for (q = p; *q && !WHITE(*q); q++)
  1573. X        ;
  1574. X
  1575. X    /* Snip off first word, copy rest of line to argument. */
  1576. X    if (*q) {
  1577. X        for (*q = '\0'; *++q && WHITE(*q); )
  1578. X        ;
  1579. X        (void)strncpy(arg, q, size);
  1580. X        arg[size - 1] = '\0';
  1581. X    }
  1582. X    else
  1583. X        arg[0] = '\0';
  1584. X    Uppercase(p);
  1585. X
  1586. X    /* Find first word in the command table. */
  1587. X    for (T = Commands; T->Name; T++)
  1588. X        if (EQ(T->Name, p))
  1589. X        return T->Value;
  1590. X
  1591. X    Nack("Unknown command");
  1592. X    }
  1593. X}
  1594. X
  1595. X
  1596. X
  1597. X
  1598. X/*
  1599. X**  Get the name of the host where the client it.
  1600. X*/
  1601. XSTATIC void
  1602. XGetClientHostname()
  1603. X{
  1604. X    struct hostent    *hp;
  1605. X    struct sockaddr_in    venial;
  1606. X    char        buff[SIZE];
  1607. X    int            size;
  1608. X
  1609. X    if (isatty(0))
  1610. X    /* Obviously a local call... */
  1611. X    TheHost = gethostname(buff, sizeof buff) < 0 ? NULL : buff;
  1612. X    else {
  1613. X    size = sizeof venial;
  1614. X    if (getpeername(0, (struct sockaddr *)&venial, &size) < 0)
  1615. X        TheHost = NULL;
  1616. X    else {
  1617. X        hp = gethostbyaddr((char *)&venial.sin_addr,
  1618. X                sizeof venial.sin_addr, AF_INET);
  1619. X        TheHost = hp ? hp->h_name : NULL;
  1620. X    }
  1621. X    }
  1622. X
  1623. X    TheHost = TheHost ? COPY(TheHost) : COPY(UnknownHost);
  1624. X    Uppercase(TheHost);
  1625. X}
  1626. X
  1627. X
  1628. X/*
  1629. X**  Read a CODA control file to see if its valid.
  1630. X*/
  1631. XSTATIC void
  1632. XCheckCodafile(p)
  1633. X    char    *p;
  1634. X{
  1635. X    ResetStorage();
  1636. X    if (!yyopen(TRUE, p)) {
  1637. X    Nack((char *)NULL);
  1638. X    exit(1);
  1639. X    }
  1640. X    if (yyparse() != BADPARSE && !HaveErrors)
  1641. X    exit(0);
  1642. X    Nack("Syntax errors found");
  1643. X    exit(1);
  1644. X}
  1645. X
  1646. X
  1647. X/*
  1648. X**  Verify a user's name and password.
  1649. X*/
  1650. XSTATIC void
  1651. XLogin(p)
  1652. X    char        *p;
  1653. X{
  1654. X    static char        BAD[] = "Bad username or password";
  1655. X    struct passwd    *pwd;
  1656. X    char        *pass;
  1657. X    char        buff[SIZE];
  1658. X
  1659. X    /* Split at the space into a name:password pair. */
  1660. X    if ((pass = strchr(p, ' ')) == NULL) {
  1661. X    Nack(BAD);
  1662. X    return;
  1663. X    }
  1664. X    *pass++ = '\0';
  1665. X
  1666. X    /* Valid name with the right password? */
  1667. X    if ((pwd = getpwnam(p)) == NULL) {
  1668. X    Nack(BAD);
  1669. X    return;
  1670. X    }
  1671. X    if (!EQ(pwd->pw_passwd, crypt(pass, pwd->pw_passwd))) {
  1672. X    Nack(BAD);
  1673. X    return;
  1674. X    }
  1675. X
  1676. X    /* Change identity. */
  1677. X    if (initgroups(p, pwd->pw_gid) < 0 || setuid(pwd->pw_uid) < 0) {
  1678. X    Nack((char *)NULL);
  1679. X    return;
  1680. X    }
  1681. X
  1682. X    /* Done; log and acknowledge it. */
  1683. X    LoggedIn = TRUE;
  1684. X    (void)sprintf(buff, "Logged in %s", p);
  1685. X    LogText(buff);
  1686. X    Ack(buff);
  1687. X}
  1688. X
  1689. X
  1690. X/*
  1691. X**  Print a usage message and exit.
  1692. X*/
  1693. XSTATIC void
  1694. XUsage()
  1695. X{
  1696. X    (void)fprintf(stderr, "Usage: codaserver %s\n",
  1697. X        "[-c] [-lLogfile] [-rCodafile] [-t]");
  1698. X    exit(1);
  1699. X}
  1700. X
  1701. X
  1702. X/* ARGSUSED1 */
  1703. Xmain(ac, av)
  1704. X    int            ac;
  1705. X    char        *av[];
  1706. X{
  1707. X    static char        LOGIN[] = "Login first";
  1708. X    register BOOL    DidRead;
  1709. X    register char    *p;
  1710. X    register COMMAND    C;
  1711. X    register int    i;
  1712. X    register TABLE    *T;
  1713. X    char        arg[SIZE];
  1714. X
  1715. X    /* Parse JCL. */
  1716. X    while ((i = getopt(ac, av, "cl:r:t")) != EOF)
  1717. X    switch (i) {
  1718. X    default:
  1719. X        Usage();
  1720. X        /* NOTREACHED */
  1721. X    case 'c':
  1722. X        Copyright();
  1723. X        exit(0);
  1724. X        /* NOTREACHED */
  1725. X    case 'l':
  1726. X        LogFile = optarg;
  1727. X        break;
  1728. X    case 'r':
  1729. X        CheckCodafile(optarg);
  1730. X        /* NOTREACHED */
  1731. X    case 't':
  1732. X        /* Play it safe... */
  1733. X        if (isatty(0)) {
  1734. X        Testing = TRUE;
  1735. X        LoggedIn = TRUE;
  1736. X        (void)printf("Testing...\n");
  1737. X        }
  1738. X        break;
  1739. X    }
  1740. X
  1741. X    /* Check for other arguments. */
  1742. X    ac -= optind;
  1743. X    av += optind;
  1744. X    if (ac)
  1745. X    Usage();
  1746. X
  1747. X    if (!Testing) {
  1748. X    /* Set up IO descriptors, be robust in the face of varying inetd's. */
  1749. X    (void)close(1);
  1750. X    (void)close(2);
  1751. X    (void)dup(0);
  1752. X    (void)dup(0);
  1753. X    }
  1754. X
  1755. X    /* Do various initializations. */
  1756. X    GetClientHostname();
  1757. X    (void)signal(SIGALRM, AlarmCatch);
  1758. X    ResetStorage();
  1759. X    LogOpen();
  1760. X
  1761. X    /* Tell client we're here. */
  1762. X    (void)sprintf(arg, "Hello %s; how are you today?", TheHost);
  1763. X    Ack(arg);
  1764. X
  1765. X    /* Read and dispatch loop. */
  1766. X    DidRead = FALSE;
  1767. X    while ((C = ReadLine(arg, sizeof arg)) != CMDquit)
  1768. X    switch (C) {
  1769. X    default:
  1770. X        Nack("Unimplemented command");
  1771. X        break;
  1772. X
  1773. X    case CMDgoto:
  1774. X        if (!LoggedIn)
  1775. X        Nack(LOGIN);
  1776. X        else if (arg[0] == '\0')
  1777. X        Nack("Directory missing");
  1778. X        else if (chdir(arg) < 0)
  1779. X        Nack((char *)NULL);
  1780. X        else
  1781. X        Ack((char *)NULL);
  1782. X        break;
  1783. X
  1784. X    case CMDhelp:
  1785. X        for (T = Commands; T->Name; T++)
  1786. X        if (T->Help) {
  1787. X            (void)sprintf(arg, "%s\t%s", T->Name, T->Help);
  1788. X            Message(arg);
  1789. X        }
  1790. X        Ack((char *)NULL);
  1791. X        break;
  1792. X
  1793. X    case CMDhost:
  1794. X        if (!Testing)
  1795. X        Nack("I already know who you are");
  1796. X        else {
  1797. X        if (TheHost) {
  1798. X            free(TheHost);
  1799. X            TheHost = NULL;
  1800. X        }
  1801. X        Uppercase(arg);
  1802. X        if (HostWasDeclared(arg)) {
  1803. X            TheHost = COPY(arg);
  1804. X            Ack((char *)NULL);
  1805. X        }
  1806. X        else
  1807. X            Nack("Host undefined");
  1808. X        }
  1809. X        break;
  1810. X
  1811. X    case CMDlist:
  1812. X        if (!LoggedIn)
  1813. X        Nack(LOGIN);
  1814. X        else if (TheHost == NULL)
  1815. X        Nack("No host specified");
  1816. X        else if (!DidRead)
  1817. X        Nack("Use READ first");
  1818. X        else
  1819. X        /* ListFiles() does its own Ack or Nack. */
  1820. X        ListFiles(arg);
  1821. X        break;
  1822. X
  1823. X    case CMDmesg:
  1824. X        LogText(arg);
  1825. X        Ack((char *)NULL);
  1826. X        break;
  1827. X
  1828. X    case CMDread:
  1829. X        if (!LoggedIn)
  1830. X        Nack(LOGIN);
  1831. X        else {
  1832. X        Rooted = FALSE;
  1833. X        AllowBinaries = TRUE;
  1834. X        ResetStorage();
  1835. X        DidRead = FALSE;
  1836. X        p = arg[0] ? arg : CONTROLFILE;
  1837. X        if (!yyopen(FALSE, p))
  1838. X            Nack((char *)NULL);
  1839. X        else {
  1840. X            if (yyparse() == BADPARSE || HaveErrors)
  1841. X            Nack("Can't parse file");
  1842. X            else {
  1843. X            LogReadfile(p);
  1844. X            if (!HostWasDeclared(TheHost)) {
  1845. X                (void)sprintf(arg, "Host \"%s\" not in the file.",
  1846. X                    TheHost);
  1847. X                Message(arg);
  1848. X            }
  1849. X            Ack((char *)NULL);
  1850. X            DidRead = TRUE;
  1851. X            }
  1852. X            yyclose();
  1853. X        }
  1854. X        }
  1855. X        break;
  1856. X
  1857. X    case CMDroot:
  1858. X        if (Rooted)
  1859. X        Nack("Permission denied");
  1860. X        else {
  1861. X        if (TheRoot)
  1862. X            free(TheRoot);
  1863. X        TheRoot = arg[0] ? COPY(arg) : NULL;
  1864. X        Ack((char *)NULL);
  1865. X        }
  1866. X        break;
  1867. X
  1868. X    case CMDsend:
  1869. X        if (!LoggedIn)
  1870. X        Nack(LOGIN);
  1871. X        else if (!DidRead)
  1872. X        Nack("Use READ first");
  1873. X        else if (arg[0])
  1874. X        /* SendFile() does its own Ack or Nack. */
  1875. X        SendFile(arg);
  1876. X        else
  1877. X        Nack("Filename missing");
  1878. X        break;
  1879. X
  1880. X    case CMDuser:
  1881. X        /* Login() does its own Ack or Nack. */
  1882. X        Login(arg);
  1883. X        break;
  1884. X
  1885. X    case CMD_time:
  1886. X        LogClose("timeout");
  1887. X        exit(0);
  1888. X        /* NOTREACHED */
  1889. X
  1890. X    }
  1891. X
  1892. X    LogClose("quit");
  1893. X    exit(0);
  1894. X    /* NOTREACHED */
  1895. X}
  1896. END_OF_FILE
  1897. if test 9605 -ne `wc -c <'server.c'`; then
  1898.     echo shar: \"'server.c'\" unpacked with wrong size!
  1899. fi
  1900. # end of 'server.c'
  1901. fi
  1902. if test -f 'server.h' -a "${1}" != "-c" ; then 
  1903.   echo shar: Will not clobber existing file \"'server.h'\"
  1904. else
  1905. echo shar: Extracting \"'server.h'\" \(5418 characters\)
  1906. sed "s/^X//" >'server.h' <<'END_OF_FILE'
  1907. X/*
  1908. X**  Copyright 1989 BBN Systems and Technologies Corporation.
  1909. X**  All Rights Reserved.
  1910. X**  This is free software, and may be distributed under the terms of the
  1911. X**  GNU Public License; see the file COPYING for more details.
  1912. X**
  1913. X**  Header file for CODA server.
  1914. X**  $Header: server.h,v 2.0 90/03/23 14:42:01 rsalz Exp $
  1915. X*/
  1916. X/* SUPPRESS 223 *//* Nested comment */
  1917. X#include <stdio.h>
  1918. X#include <sys/types.h>
  1919. X
  1920. X
  1921. X/*
  1922. X**  Constants, compilation control, et cetera.
  1923. X*/
  1924. X
  1925. X/* Assorted constants. */
  1926. X#define TRUE        1        /* Any non-zero value        */
  1927. X#define FALSE        0        /* Must be zero            */
  1928. X#define BADPARSE    1        /* Returned by YACC; must be 1    */
  1929. X#define SIZE        256        /* String buffer size        */
  1930. X#define MAXPATH        1024        /* Maximum pathname length    */
  1931. X#define HOST_DELTA    10        /* Clump for growing host array    */
  1932. X#define CLASS_DELTA    10        /* Clump for class arrays    */
  1933. X#define ITEM_DELTA    50        /* Clump for those other things    */
  1934. X#define SCAN_PING    200        /* How often to say we're alive    */
  1935. X#define FASTDEPTH    6        /* How far before closedir()?    */
  1936. X#define FW_NOFURTHER    1        /* FileWalker, go no further    */
  1937. X#define FW_PROCEED    2        /* FileWalker, keep going    */
  1938. X#define FW_EXIT        3        /* FileWalker, exit and pop up    */
  1939. X
  1940. X/* Compile in RCS id strings? */
  1941. X#ifndef    SABER
  1942. X#define RCSID
  1943. X#endif    /* SABER */
  1944. X
  1945. X/* Give up after this many seconds of inactivity. */
  1946. X#define TIMEOUT        (30 * 60)
  1947. X
  1948. X/* Default name of the log file. */
  1949. X#define LOGFILE        "/usr/spool/log/codalog"
  1950. X
  1951. X/* Default name of the file to read. */
  1952. X#define CONTROLFILE    "Codafile"
  1953. X
  1954. X/* Name of the built-in class that contains all hosts except UnknownHost. */
  1955. X#define ALL        "_ALL"
  1956. X
  1957. X/* Default name if host name isn't found. */
  1958. X#define GUESTHOST    "_ANYHOST"
  1959. X
  1960. X/* Return type of a signal-handling function. */
  1961. Xtypedef int        CATCHER;    /* .. */
  1962. X/* typedef void        CATCHER;    /* .. */
  1963. X
  1964. X/* Hide routines that can be hidden? */
  1965. X#define STATIC        static        /* .. */
  1966. X/*efine STATIC        /* NULL */    /* .. */
  1967. X
  1968. X#define WHITE(c)    ((c) == ' ' || (c) == '\t')
  1969. X
  1970. X/* Shut up, okay? */
  1971. X#ifdef    lint
  1972. X#undef putc
  1973. X#undef putchar
  1974. X#undef ungetc
  1975. X#undef RCSID
  1976. X#endif    /* lint */
  1977. X
  1978. X/* Memory allocation. */
  1979. X#define NEW(T, c)        \
  1980. X    ((T *)malloc((unsigned int)(sizeof (T) * (c))))
  1981. X#define GROW(p, T, c)        \
  1982. X    ((T *)realloc((char *)p, (unsigned int)(sizeof (T) * (c))))
  1983. X#define COPY(p)            \
  1984. X    strcpy(NEW(char, strlen(p) + 1), p)
  1985. X
  1986. X/* Fast front-end for string comparison. */
  1987. X#define EQ(p, q)        \
  1988. X    ((p) == (q) || ((p)[0] == (q)[0] && strcmp((p), (q)) == 0))
  1989. X
  1990. X
  1991. X
  1992. X/*
  1993. X**  List of server commands.
  1994. X*/
  1995. Xtypedef enum _COMMAND {
  1996. X    CMDgoto,
  1997. X    CMDhelp,
  1998. X    CMDhost,
  1999. X    CMDlist,
  2000. X    CMDmesg,
  2001. X    CMDquit,
  2002. X    CMDread,
  2003. X    CMDroot,
  2004. X    CMDsend,
  2005. X    CMDuser,
  2006. X    CMD_time
  2007. X} COMMAND;
  2008. X
  2009. X
  2010. X/*
  2011. X**  Is it, or is it not?
  2012. X*/
  2013. Xtypedef int    BOOL;
  2014. X
  2015. X
  2016. X/*
  2017. X**  A linked list of strings.
  2018. X*/
  2019. Xtypedef struct _STRLIST {
  2020. X    struct _STRLIST    *Next;
  2021. X    char        *Value;
  2022. X} STRLIST;
  2023. X
  2024. X
  2025. X/*
  2026. X**  An exception is a pattern for either files or a directory that is
  2027. X**  valid for a class of hosts.
  2028. X*/
  2029. Xtypedef struct _EXCEPTION {
  2030. X    struct _EXCEPTION    *Next;
  2031. X    STRLIST        *Value;
  2032. X    BOOL        Directory;
  2033. X    char        *Class;
  2034. X} EXCEPTION;
  2035. X
  2036. X
  2037. X/*
  2038. X**  A directory list is a linked list of pathnames and their exceptions.
  2039. X*/
  2040. Xtypedef struct _DIRLIST {
  2041. X    struct _DIRLIST    *Next;
  2042. X    char        *Value;
  2043. X    BOOL        Directory;
  2044. X    EXCEPTION        *Exceptions;
  2045. X} DIRLIST;
  2046. X
  2047. X
  2048. X/*
  2049. X**  A block has a name, whether it is part of the default list, a list of
  2050. X**  files, and a class that it is valid for.
  2051. X*/
  2052. Xtypedef struct _BLOCK {
  2053. X    struct _BLOCK    *Next;
  2054. X    char        *Name;
  2055. X    BOOL        Excluded;
  2056. X    DIRLIST        *Directories;
  2057. X    char        *Class;
  2058. X} BLOCK;
  2059. X
  2060. X
  2061. X/*
  2062. X**  An item is something that can be sent to a client.  It has permissions,
  2063. X**  a modification time, and might be a directory.
  2064. X*/
  2065. Xtypedef struct _ITEM {
  2066. X    char        *Name;
  2067. X    int            Uid;
  2068. X    int            Gid;
  2069. X    BOOL        Directory;
  2070. X    long        Size;
  2071. X    time_t        Time;
  2072. X    int            Mode;
  2073. X} ITEM;
  2074. X
  2075. X
  2076. X/*
  2077. X**  Data is declared everywhere, lives oncewhere.
  2078. X*/
  2079. X#ifdef    MAINLINE
  2080. X#define EXTERN        /* NULL */
  2081. X#else
  2082. X#define EXTERN        extern
  2083. X#endif    /* MAINLINE */
  2084. X
  2085. XEXTERN BLOCK    BaseBlock;        /* Chain of known blocks    */
  2086. XEXTERN BOOL    AllowBinaries;        /* Don't check for a.out files?    */
  2087. XEXTERN BOOL    Rooted;            /* Can client set the root?    */
  2088. Xextern char    UnknownHost[];        /* Name of the unknown host    */
  2089. Xextern char    *LogFile;        /* Name of the log file        */
  2090. XEXTERN char    *TheHost;        /* Host that called us        */
  2091. XEXTERN char    *TheRoot;        /* Root for relative pathnames    */
  2092. XEXTERN int    HaveErrors;        /* Failed to parse Codafile?    */
  2093. XEXTERN ITEM    *BaseItem;        /* Array of things to send    */
  2094. XEXTERN int    NumItem;        /* Size of said array        */
  2095. X
  2096. X/* Our routines. */
  2097. XBLOCK        *FindBlock();
  2098. XITEM        *FindItem();
  2099. Xchar        *strerror();
  2100. Xint        HostIsInClass();
  2101. Xint        yyopen();
  2102. Xint        yyparse();
  2103. Xvoid        Ack();
  2104. Xvoid        AddClassesToClass();
  2105. Xvoid        AddHostToClass();
  2106. Xvoid        AddItemToList();
  2107. Xvoid        Data();
  2108. Xvoid        DefineBlock();
  2109. Xvoid        DefineHost();
  2110. Xvoid        ListFiles();
  2111. Xvoid        LogClose();
  2112. Xvoid        LogOpen();
  2113. Xvoid        LogReadfile();
  2114. Xvoid        LogSentItem();
  2115. Xvoid        LogText();
  2116. Xvoid        Message();
  2117. Xvoid        Nack();
  2118. Xvoid        ResetItem();
  2119. Xvoid        ResetStorage();
  2120. Xvoid        SendFile();
  2121. Xvoid        SortItem();
  2122. Xvoid        Uppercase();
  2123. Xvoid        yyclose();
  2124. Xvoid        yyerror();
  2125. X
  2126. X/* From the C library. */
  2127. Xextern int    errno;
  2128. Xextern int    optind;
  2129. Xextern time_t    time();
  2130. Xextern char    *optarg;
  2131. Xextern char    *bsearch();
  2132. Xextern char    *crypt();
  2133. Xextern char    *getwd();
  2134. Xextern char    *malloc();
  2135. Xextern char    *realloc();
  2136. Xextern char    *sprintf();        /* Too painful, my ass        */
  2137. Xextern char    *strcat();
  2138. Xextern char    *strchr();
  2139. Xextern char    *strcpy();
  2140. Xextern char    *strncpy();
  2141. Xextern char    *strrchr();
  2142. END_OF_FILE
  2143. if test 5418 -ne `wc -c <'server.h'`; then
  2144.     echo shar: \"'server.h'\" unpacked with wrong size!
  2145. fi
  2146. # end of 'server.h'
  2147. fi
  2148. echo shar: End of archive 2 \(of 3\).
  2149. cp /dev/null ark2isdone
  2150. MISSING=""
  2151. for I in 1 2 3 ; do
  2152.     if test ! -f ark${I}isdone ; then
  2153.     MISSING="${MISSING} ${I}"
  2154.     fi
  2155. done
  2156. if test "${MISSING}" = "" ; then
  2157.     echo You have unpacked all 3 archives.
  2158.     rm -f ark[1-9]isdone
  2159. else
  2160.     echo You still need to unpack the following archives:
  2161.     echo "        " ${MISSING}
  2162. fi
  2163. ##  End of shell archive.
  2164. exit 0
  2165. exit 0 # Just in case...
  2166.